#ifndef FHE_CORE_NODEFACTORY_H
#define FHE_CORE_NODEFACTORY_H

#include <fhe/core/INodeDesc.h>
#include <fhe/core/INodeInterface.h>
#include <set>

namespace fhe
{
  namespace core
  {
    class FHE_API NodeFactory
    {
    public:
      static NodeFactory& instance();
      ~NodeFactory();
      
      Node* buildNode( const std::string& module, const std::string& name );
      
      void loadModule( const std::string& module );
      
      INodeDesc::Ptr getNodeDesc( const std::string& module, const std::string& name ) const;
      bool hasNodeDesc( const std::string& module, const std::string& name ) const;
      void addNodeDesc( const INodeDesc::Ptr& nodeDesc );
      typedef std::vector< INodeDesc::Ptr >::const_iterator NodeDescIterator;
      NodeDescIterator nodeDescsBegin() const;
      NodeDescIterator nodeDescsEnd() const;
      
      INodeInterface::Ptr getNodeInterface( const std::string& module, const std::string& name ) const;
      bool hasNodeInterface( const std::string& module, const std::string& name ) const;
      void addNodeInterface( const INodeInterface::Ptr& nodeInterface );
      typedef std::vector< INodeInterface::Ptr >::const_iterator NodeInterfaceIterator;
      NodeInterfaceIterator nodeInterfacesBegin() const;
      NodeInterfaceIterator nodeInterfacesEnd() const;

    private:
      std::vector< INodeDesc::Ptr > nodeDescs_;
      std::vector< INodeInterface::Ptr > nodeInterfaces_;
      std::set< std::string > modules_;
      
      NodeFactory();
      NodeFactory( const NodeFactory& );
      void operator=( const NodeFactory& );
    };
  }
}

#endif
